package clientWeb;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.ext.xml.DomRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.ClientResource;
import org.restlet.resource.ResourceException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * Servlet qui sera cliente d'un service web, elle recevra le XML à transmettre à la vue
 * et elle créera les XML (post, put) à envoyer au service web
 */
public class clientWebServlet extends HttpServlet {
   
    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        
        request.setCharacterEncoding("UTF-8");

        //Aiguilleur

        String action = request.getParameter("action");
        String getXML = request.getParameter("getXML");
        String forward = null;
        try {

            if (action == null) {
                 if(getXML == null)
                     forward = "Debut";
                 else
                     ecrireXMLResponse(getXML, request, response);
                
            } else if (action.equals("getBases"))
            {
                forward = getBases(request);
            } else if (action.equals("getBase"))
            {
                forward = getBase(request);
            } else if (action.equals("getTable"))
            {
                forward = getTable(request);
            } else if (action.equals("getRecord"))
            {
                forward = getRecord(request);
            } else if (action.equals("commande"))
            {
                forward = commande(request);
            } else if (action.equals("postRecord"))
            {
                forward = postRecord(request);
            } else if (action.equals("modifierRecord"))
            {
                forward = modifierRecord(request);
            } else if (action.equals("deleteRecord"))
            {
                forward = deleteRecord(request);
            } 
            else //Si l'action est inconnue
            {
                forward = erreur(request);
            }
        } catch (Exception e) {
            forward = "VueErreur";
            request.setAttribute("erreur", "Erreur.");
        }

        if(getXML == null)
            request.getRequestDispatcher(forward + ".jsp").forward(request, response);

    } 

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    } 

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

    private String getBases(HttpServletRequest request)
    {
        String URLServeur = request.getParameter("URLServeur");

        if(URLServeur != null)
        {
            request.getSession().setAttribute("URLServeur", URLServeur);
        }

        return "PageBases";
    }

    private String getBase(HttpServletRequest request)
    {
        String nomBase = request.getParameter("nomBase");

        String URLServeur = (String) request.getSession().getAttribute("URLServeur");

        request.getSession().setAttribute("nomBase", nomBase);
        request.setAttribute("URLBase", URLServeur + "/bases/"+ nomBase);

        return "PageTables";
    }

    private String getTable(HttpServletRequest request)
    {
        String URLServeur = (String) request.getSession().getAttribute("URLServeur");
        String nomBase = (String) request.getSession().getAttribute("nomBase");

        String nomTable = request.getParameter("nomTable");

        request.setAttribute("URLBase", URLServeur + "/bases/" + nomBase);
        request.setAttribute("URLTable", URLServeur + "/bases/" + nomBase + "/tables/" + nomTable + "/records");
        request.setAttribute("nomTable", nomTable);

        return "PageTables";
    }

    private String getRecord(HttpServletRequest request)
    {
        String URLServeur = (String) request.getSession().getAttribute("URLServeur");
        String nomBase = (String) request.getSession().getAttribute("nomBase");

        String nomTable = request.getParameter("nomTable");
        String identifiant = request.getParameter("idprimarykey");

        request.setAttribute("URLBase", URLServeur + "/bases/" + nomBase);
        request.setAttribute("URLRecord", URLServeur + "/bases/" + nomBase + "/tables/" + nomTable + "/records/" + identifiant);
        request.setAttribute("nomTable", nomTable);
        
        return "PageTables";
    }

    private String commande(HttpServletRequest request)
    {
        String URLServeur = (String) request.getSession().getAttribute("URLServeur");
        String nomBase = (String) request.getSession().getAttribute("nomBase");

        String ordre = request.getParameter("ordre");
        String nomTable = request.getParameter("nomTable");

        if(ordre.equals("Nouvel enregistrement"))
        {
            request.setAttribute("URLTableSchema", URLServeur + "/bases/" + nomBase + "/tables/" + nomTable + "/schema");
        }
        else if(ordre.equals("modifier"))
        {
            String identifiant = request.getParameter("idprimarykey");
            request.setAttribute("URLRecord", URLServeur + "/bases/" + nomBase + "/tables/" + nomTable + "/records/" + identifiant);
            request.setAttribute("nomTable", nomTable);
        }

        request.setAttribute("URLBase", URLServeur + "/bases/" + nomBase);
        request.setAttribute("ordre", ordre);

        return "PageTables";
    }

    private String postRecord(HttpServletRequest request)
    {
        String URLServeur = (String) request.getSession().getAttribute("URLServeur");
        String nomBase = (String) request.getSession().getAttribute("nomBase");

        String nomTable = request.getParameter("nomTable");

        String url = URLServeur + "/bases/" + nomBase + "/tables/" + nomTable + "/records";

        Map m = request.getParameterMap();
        Iterator itr = m.entrySet().iterator();
           
        try
        {
            //Création d'un XML
            DomRepresentation dom = new DomRepresentation(MediaType.TEXT_XML);
            Document doc = dom.getDocument();
            Element table = doc.createElement(nomTable);
            doc.appendChild(table);
            Element row = doc.createElement("row");
            table.appendChild(row);
            while(itr.hasNext())
            {
                //Ajout de chaque colonne
                Map.Entry pairs = (Map.Entry) itr.next();
                if(!((String) pairs.getKey()).equals("action")
                        && !((String) pairs.getKey()).equals("nomTable"))
                {
                    Element colonne = doc.createElement((String) pairs.getKey());
                    colonne.appendChild(doc.createTextNode(((String[]) pairs.getValue())[0]));
                    row.appendChild(colonne);
                }
            }

            ClientResource resource = getClientResource(request, url);
            resource.post(dom);
            request.setAttribute("message", "Enregistrement correctement créé");

        } catch (ResourceException exc) {
            Status expStatus = Status.CLIENT_ERROR_NOT_FOUND;
            request.setAttribute("message", "Erreur lors de la création");
        } catch (IOException exc) {
            Status expStatus = Status.CLIENT_ERROR_NOT_FOUND;
            request.setAttribute("message", "Erreur lors de la création");
        } 
        
        return getTable(request);
    }

    private String modifierRecord(HttpServletRequest request)
    {
        String URLServeur = (String) request.getSession().getAttribute("URLServeur");
        String nomBase = (String) request.getSession().getAttribute("nomBase");

        String nomTable = request.getParameter("nomTable");
        String identifiant = request.getParameter("idprimarykey");

        String url = URLServeur + "/bases/" + nomBase + "/tables/" + nomTable + "/records/" + identifiant;

        Map m = request.getParameterMap();
        Iterator itr = m.entrySet().iterator();

        try
        {
            //Création du XML
            DomRepresentation dom = new DomRepresentation(MediaType.TEXT_XML);
            Document doc = dom.getDocument();
            Element table = doc.createElement(nomTable);
            doc.appendChild(table);
            Element row = doc.createElement("row");
            table.appendChild(row);
            while(itr.hasNext())
            {
                //Ajout de chaque colonne
                Map.Entry pairs = (Map.Entry) itr.next();
                if(!((String) pairs.getKey()).equals("action")
                        && !((String) pairs.getKey()).equals("nomTable")
                        && !((String) pairs.getKey()).equals("idprimarykey"))
                {
                    Element colonne = doc.createElement((String) pairs.getKey());
                    colonne.appendChild(doc.createTextNode(((String[]) pairs.getValue())[0]));
                    row.appendChild(colonne);
                }
            }

            ClientResource resource = getClientResource(request, url);
            resource.put(dom);
            request.setAttribute("message", "Enregistrement correctement modifié");

        } catch (ResourceException exc) {
            Status expStatus = Status.CLIENT_ERROR_NOT_FOUND;
            request.setAttribute("message", "Erreur lors de la modification");
        } catch (IOException exc) {
            Status expStatus = Status.CLIENT_ERROR_NOT_FOUND;
            request.setAttribute("message", "Erreur lors de la modification");
        } 

        return getTable(request);
    }

    private String deleteRecord(HttpServletRequest request)
    {
        String URLServeur = (String) request.getSession().getAttribute("URLServeur");
        String nomBase = (String) request.getSession().getAttribute("nomBase");

        String nomTable = request.getParameter("nomTable");
        String identifiant = request.getParameter("idprimarykey");

        String url = URLServeur + "/bases/" + nomBase + "/tables/" + nomTable + "/records/" + identifiant;

        try
        {
            ClientResource resource = getClientResource(request, url);
            resource.delete();
            request.setAttribute("message", "Enregistrement correctement supprimé");

        } catch (ResourceException exc) {
            Status expStatus = Status.CLIENT_ERROR_NOT_FOUND;
            request.setAttribute("message", "Erreur lors de la suppression");
        }
        
        return getTable(request);

    }

    /**
     * Dans le cas d'une requête de type getXML, on écrit dans la response.getWriter()
     * le XML demandé
     * @param url : la ressource demandée au service web
     * @param request
     * @param response
     */
    public static void ecrireXMLResponse(String url, HttpServletRequest request, HttpServletResponse response)
     {
        try
        {
            response.setContentType("text/xml;charset=UTF-8");
            PrintWriter out = response.getWriter();

            ClientResource resource = getClientResource(request, url);

            try {
                Representation representation = resource.get(MediaType.TEXT_XML);
                representation.write(out);
            } catch (ResourceException exc) {
                Status expStatus = Status.CLIENT_ERROR_NOT_FOUND;
            } finally {
                out.close();
            }

            }
        catch(IOException e)
        {
            Status expStatus = Status.SERVER_ERROR_INTERNAL;
        }
    }

    /**
     * On évite de recréer la connexion à chaque fois, si elle existe déjà on s'en sert
     * et on la sauvegarde
     * @param url : La ressource demandée au service web
     * @return la connexion, nouvelle ou existante
     */
    private static ClientResource getClientResource(HttpServletRequest request, String url)
    {
        ClientResource resource = (ClientResource) request.getSession().getAttribute("ClientResource");
        if(resource == null)
        {
            //Première connexion
            resource = new ClientResource(url);
            request.getSession().setAttribute("ClientResource", resource);
        }
        else
        {
            //Réutilisation de la connexion
            resource.setReference(url);
        }

        return resource;
    }
   

    /**
     * Cette fonction n'est plus utilisée.
     * Elle permettait d'écrire le XML reçu de la part du service web sur un fichier xml
     * @param request
     */
    private void ecrireXMLFichier(HttpServletRequest request, String nomFichier)
    {
        try
        {
            URL url = new URL((String) request.getAttribute("URL"));
            URLConnection uc = url.openConnection();
            InputStreamReader isr = new InputStreamReader(uc.getInputStream());
            BufferedReader  br = new BufferedReader(isr, 512);

            String baseDir = getServletContext().getRealPath("/");

            FileOutputStream fos = new FileOutputStream(baseDir + nomFichier);
            BufferedOutputStream bos = new BufferedOutputStream(fos, 512);

            int lect = br.read();
            while(lect > -1)
            {
                bos.write(lect);
                lect = br.read();
            }

            br.close();
            bos.close();
        }
        catch(IOException e)
        {
            //Supprimer l'xml s'il existait déjà d'une ancienne requête
            String baseDir = getServletContext().getRealPath("/");
            File f = new File(baseDir + nomFichier);
            if (f.exists())
                f.delete();
        }
    }

    private String erreur(HttpServletRequest request) {
        request.setAttribute("erreur", "Page inexistante.");
        return "VueErreur";
    }

}
